package com.deeper.customview.ui.c9.demo.c09d02;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Scroller;

public class FlingRemovedListView extends ListView {
    private static final String TAG = "FlingRemovedListView";
    private static final float SNAP_VELOCITY = 600;
    private final int scaledTouchSlop;
    private VelocityTracker velocityTracker;
    private int firstY;
    private float preX;
    private int firstX;
    private int position;
    private View willFlingView;
    private boolean isSlide;

    private static final int SLIDE_MASK = 0x1;//是否可以滑动
    private static final int IS_ROLLBACK_MASK = SLIDE_MASK << 1;//是否回滚，如果回退不能删除列表项
    private int flags = 0;//标识位
    private final Scroller scroller;


    public FlingRemovedListView(Context context) {
        this(context, null);
    }


    public FlingRemovedListView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public FlingRemovedListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        scroller = new Scroller(context);
        scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        obtainVelocity(ev);

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (!scroller.isFinished()) {
                    return super.dispatchTouchEvent(ev);
                }
                firstX = (int) (preX = x);
                firstY = y;
                position = this.pointToPosition(x, y);
                if (position != INVALID_POSITION) {
                    int visibleIndex = position - getFirstVisiblePosition();
                    willFlingView = getChildAt(visibleIndex);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                float xVelocity = velocityTracker.getXVelocity();
                if (x > firstX && (Math.abs(xVelocity) > SNAP_VELOCITY
                        || Math.abs(x - firstX) > scaledTouchSlop
                        && Math.abs(y - firstY) < scaledTouchSlop)) {
                    flags |= SLIDE_MASK;
                }
                break;
            case MotionEvent.ACTION_UP:
                releaseVelocity();
                break;
        }
        return super.dispatchTouchEvent(ev);
    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if ((flags & SLIDE_MASK) == SLIDE_MASK
                && position != INVALID_POSITION
                && willFlingView != null) {
            float x = ev.getX();
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    break;
                case MotionEvent.ACTION_MOVE:
                    float dx = preX - x;
                    willFlingView.scrollBy((int) dx, 0);
                    preX = x;
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    int scrollX = willFlingView.getScrollX();
                    int listViewWidth = getMeasuredWidth();
                    if (Math.abs(scrollX) > listViewWidth / 2) {
                        //继续滑动
                        int remain = scrollX + listViewWidth;
                        scroller.startScroll(scrollX, 0, -remain, 0, Math.abs(remain));
                        flags &= ~IS_ROLLBACK_MASK;
                    } else {
                        //回退
                        scroller.startScroll(scrollX, 0, -scrollX, 0, Math.abs(scrollX));
                        flags |= IS_ROLLBACK_MASK;
                    }

                    postInvalidate();
                    flags &= ~SLIDE_MASK;
                    break;
            }
            return true;
        }
        return super.onTouchEvent(ev);
    }


    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            willFlingView.scrollTo(scroller.getCurrX(), 0);
            postInvalidate();
            if (scroller.isFinished()) {
                if (onRemovedItemListener != null) {
                    //没有回退，则删除列表项
                    if ((flags & IS_ROLLBACK_MASK) != IS_ROLLBACK_MASK) {
                        onRemovedItemListener.itemRemoved(position, getAdapter());
                        willFlingView.scrollTo(0, 0);
                    }
                }
            }
        }
    }


    private void obtainVelocity(MotionEvent ev) {
        if (velocityTracker == null) {
            velocityTracker = VelocityTracker.obtain();
        }
        velocityTracker.addMovement(ev);
    }


    private void releaseVelocity() {
        if (velocityTracker != null) {
            velocityTracker.clear();
            velocityTracker.recycle();
            velocityTracker = null;
        }
    }


    private OnRemovedItemListener onRemovedItemListener;

    public interface OnRemovedItemListener {
        void itemRemoved(int position, ListAdapter adapter);
    }


    public void setOnRemovedItemListener(OnRemovedItemListener onRemovedItemListener) {
        this.onRemovedItemListener = onRemovedItemListener;
    }
}
